/* DwrResponse.java
 *
 * Copyright 2006, Tim Dwelle.
 *
 * Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See
 * the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

package dowry.dwr;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/**
 * DwrResponse is a wrapper to the actual servlet response,
 * allowing us to capture whether an error occured during
 * the processing of the response.  This is determined by
 * inspecting the data DWR sends to the response's
 * print writer.
 *
 */
public class DwrResponse extends HttpServletResponseWrapper
{
    private DwrPrintWriter pw  = null;
    private String contentType = null;
    private int status         = -1;

    /**
     * Construct a wrapper to the provided servlet response
     * instance.
     *
     * @param res  the servlet response to be wrapped
     *
     */
    public DwrResponse(HttpServletResponse res)
    {
        super(res);
    }

    /**
     * Returns a PrintWriter object that inspects the data
     * DWR writes to it, checking for DWR's marshalling
     * errors to the client.
     *
     * @return   the wrapped PrintWriter
     *
     */
    public PrintWriter getWriter()
    {
        if (pw == null)
        {
            pw = new DwrPrintWriter();
        }

        return pw;
    }

    /**
     * Don't actually print anything until the commit is
     * called.  Since we are not wrapping every overloaded
     * version of <code>print()</code>, this could be ugly
     * if not used carefully!
     *
     */
    public void commit()
    {
        if (status > -1)
        {
            super.setStatus(status);
        }

        if (contentType != null)
        {
            super.setContentType(contentType);
        }

        if (pw != null)
        {
            try
            {
                pw.commit(super.getWriter());
            }
            catch(IOException ioex)
            {
            }
        }
    }

    /**
     * Returns whether or not DWR has written an error to
     * the response.
     *
     * @return   true if an error was detected; false
     *           otherwise
     *
     */
    public boolean isError()
    {
        boolean err = false;

        if (pw != null)
        {
            err = pw.isError();
        }

        return err;
    }

    /**
     * Overrides the servlet request's implementation of
     * <code>setContentType()</code>, such that we won't
     * actually set the content type until we <code>commit()
     * </code>.
     *
     * @param s  the content type to be set
     *
     */
    public void setContentType(String s)
    {
        contentType = s;
    }

    /**
     * Manually resets the error flag for this response,
     * as returned by <code>isError()</code>, to the
     * specified value.  Note that it is possible to call to
     * <code>setError(false)</code> and still have
     * <code>isError()</code> return <code>true</code>, if
     * an error is detected after the error flag is set, but
     * before it is read again.
     *
     * @param b  the boolean error condition to set
     *           the response to
     *
     */
    public void setError(boolean b)
    {
        if (pw != null)
        {
            pw.setError(b);
        }
    }

    /**
     * Overrides the servlet request's implementation of
     * <code>setStatus()</code>, such that we won't
     * actually set the status until we <code>commit()
     * </code>.
     *
     * @param i  the status to be set
     *
     */
    public void setStatus(int i)
    {
        status = i;
    }
}